package com.example.demoreferencetype.service;

import com.example.demoreferencetype.Model.Goods;

import java.lang.ref.*;
import java.lang.reflect.Field;
import java.util.*;

/**
 * 类${CLASS_NAME}的实现描述：
 *
 * @Author liyanjun 2019-01-30 13:18
 */
public class DemoTest {

    public static boolean isRun = true;

    public static void main(String[] args) throws Exception {
//        strongReference();
//        softReference();
//        softReferenceDynamic();
//        weakReference();
        weakReferenceDynamic();
//        phantomReference();
//        test();
    }

    /**
     * 强引用
     */
    private static void strongReference() {
        Goods g = new Goods("1", "mobile");
        g = null;
    }

    /**
     * 软引用-手动GC
     */
    private static void softReference() {
        byte[] bytes = new byte[1024 * 1024 * 1024];
        SoftReference<byte[]> softReference = new SoftReference<>(bytes);
        System.out.println("softReferences:" + softReference.get());
        bytes = null;
        System.out.println("softReferences:" + softReference.get());
        System.gc();
        System.out.println("softReferences:" + softReference.get());
        byte[] bytes2 = new byte[1024 * 1024 * 1024];
        //System.gc();
        System.out.println("softReferences:" + softReference.get());
    }

    /**
     * 软引用-动态GC
     * jps 查看pid
     * jstat -gcutil pid interval(ms)
     */
    private static void softReferenceDynamic() {
        List<SoftReference<byte[]>> c = new ArrayList<>();
        int lastCount = 0;
        while (true) {
            byte[] bytes = new byte[90024];
            SoftReference<byte[]> softReference = new SoftReference<>(bytes);
            c.add(softReference);
            int i = 0;
            for (SoftReference<byte[]> o : c) {
                if (o.get() == null) {
                    i++;
                }
            }
            if (i > lastCount) {
                lastCount = i;
                System.out.println("O趋于100%，有FGC发生，有软引用被回收");
                System.out.println(c.size() + "-" + i);
            }
        }
    }

    /**
     * 弱引用-手动GC
     */
    private static void weakReference() {
        Goods g = new Goods("1", "mobile");
        WeakReference<Goods> weakReference = new WeakReference<>(g);
        System.out.println("weakReference:" + weakReference.get());
        g = null;
        System.out.println("weakReference:" + weakReference.get());
        System.gc();
        System.out.println("weakReference:" + weakReference.get());
    }

    /**
     * 弱引用-动态GC
     * jps 查看pid
     * jstat -gcutil pid interval(ms)
     */
    private static void weakReferenceDynamic() {
        List<WeakReference<byte[]>> c = new ArrayList<>();
        int lastCount = 0;
        while (true) {
            byte[] bytes = new byte[1024];
            WeakReference<byte[]> weakReference = new WeakReference<>(bytes);
            c.add(weakReference);
            int i = 0;
            for (WeakReference<byte[]> o : c) {
                if (o.get() == null) {
                    i++;
                }
            }
            if (i > lastCount) {
                lastCount = i;
                System.out.println("Eden趋于100%，有GC发生，有弱引用被回收");
                System.out.println(c.size() + "-" + i);
            }
        }
    }

    /**
     * 虚引用
     */
    private static void phantomReference() throws InterruptedException {
        Goods g = new Goods("1", "mobile");
        ReferenceQueue<Goods> referenceQueue = new ReferenceQueue<Goods>();
        PhantomReference<Goods> phantomReference = new PhantomReference<>(g, referenceQueue);
        System.out.println("phantomReference:" + phantomReference.get());

        new Thread() {
            public void run() {
                Long b = new Date().getTime();
                while (isRun) {
                    Object obj = referenceQueue.poll();
                    Long c = new Date().getTime();
                    if (Objects.isNull(obj) && c - b > 1000) {
                        b = c;
                        System.out.println("no phantomReference to be collected");
                    }
                    if (!Objects.isNull(obj)) {
                        try {
                            Field referent = Reference.class.getDeclaredField("referent");
                            referent.setAccessible(true);
                            Object result = referent.get(obj);
                            System.out.println("gc will collect：" + result.getClass() + "@" + result.toString());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }.start();

        g = null;
        Thread.currentThread().sleep(3000);
        //System.gc();  
        Thread.currentThread().sleep(3000);
        isRun = false;
    }

    /**
     * 弱引用的应用
     */
    private static void test() {
        Map map;
        map = new WeakHashMap<String, Object>();
        for (int i = 0; i < 100000; i++) {
            map.put("key" + i, new byte[i]);
        }

        map = new HashMap<String, Object>();
        for (int i = 0; i < 100000; i++) {
            map.put("key" + i, new byte[i]);
        }
    }
}
